﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Heritage.Codebox;
using Heritage.Logging;
using Heritage.Models;
using System.Text;

namespace Heritage.Controllers
{
    public class GameController : Controller
    {
        [AuthorizedValidated]
        public ActionResult Join(string id)
        {
            JoinModel model = new JoinModel();
            model.GameName = id;
            Users user = Utils.GetCurrentUser();
            ViewData.Model = model;
            if (!Utils.IsGameExists(id))
            {
                model.ErrorText = "Запись невозможна - такой партии не существует!<br><span style=\"font-size:10px;\">(а хулиганить и писать в адресной строке что попало - нехорошо)</span>";
                LogService.Warn(Utils.GetPrincipalName(), Constants.COMPONENT_SITE, string.Format("Trying to join non-existent game: {0}", id));
                return View();
            }
            if (!Utils.IsGameAvailable(id))
            {
                model.ErrorText = "Запись невозможна - партия уже стартовала!";
                LogService.Warn(Utils.GetPrincipalName(), Constants.COMPONENT_SITE, string.Format("Trying to join started game: {0}", id));
                return View();
            }
            if (!Utils.IsGameHasRoom(id))
            {
                model.ErrorText = "Запись невозможна - партия уже заполнена!";
                LogService.Warn(Utils.GetPrincipalName(), Constants.COMPONENT_SITE, string.Format("Trying to join full game: {0}", id));
                return View();
            }
            if (Utils.UserInGame(user.ID, id))
            {
                model.ErrorText = "Запись невозможна - вы уже записаны в эту партию!";
                LogService.Warn(Utils.GetPrincipalName(), Constants.COMPONENT_SITE, string.Format("Trying to join game already joined: {0}", id));
                return View();
            }
            if (!Utils.UserHasRating(user.ID, id))
            {
                model.ErrorText = "Запись невозможна - ваш игровой рейтинг слишком низок для записи в эту партию!";
                LogService.Warn(Utils.GetPrincipalName(), Constants.COMPONENT_SITE, string.Format("Trying to join game with insufficient rating: {0}", id));
                return View();
            }
            Games g = Utils.GetGame(id);
            if (g.Password != null)
            {
                model.GamePassword = g.Password;
            }
            return View();
        }

        [AcceptVerbs(HttpVerbs.Post)]
        [AuthorizedValidated]
        public ActionResult Join(FormCollection coll)
        {
            JoinModel model = new JoinModel();
            Users user = Utils.GetCurrentUser();
            model.GameName = coll["game"];
            model.GameMask = coll["mask"];
            model.GameEmail = coll["gemail"];
            model.GameEmailPassword = coll["gpassword"];
            model.Gender = int.Parse(coll["gender"]);
            model.GamePassword = coll["password"];
            ViewData.Model = model;
            if (!Utils.IsGameExists(model.GameName))
            {
                model.ErrorText = "Запись невозможна - такой партии не существует!<br><span style=\"font-size:10px;\">(а хулиганить и писать в адресной строке что попало - нехорошо)</span>";
                LogService.Warn(Utils.GetPrincipalName(), Constants.COMPONENT_SITE, string.Format("Trying to join non-existent game: {0}", model.GameName));
                return View();
            }
            if (!Utils.IsGameAvailable(model.GameName))
            {
                model.ErrorText = "Запись невозможна - партия уже стартовала!";
                LogService.Warn(Utils.GetPrincipalName(), Constants.COMPONENT_SITE, string.Format("Trying to join started game: {0}", model.GameName));
                return View();
            }
            if (!Utils.IsGameHasRoom(model.GameName))
            {
                model.ErrorText = "Запись невозможна - партия уже заполнена!";
                LogService.Warn(Utils.GetPrincipalName(), Constants.COMPONENT_SITE, string.Format("Trying to join full game: {0}", model.GameName));
                return View();
            }
            if (Utils.UserInGame(user.ID, model.GameName))
            {
                model.ErrorText = "Запись невозможна - вы уже записаны в эту партию!";
                LogService.Warn(Utils.GetPrincipalName(), Constants.COMPONENT_SITE, string.Format("Trying to join game already joined: {0}", model.GameName));
                return View();
            }
            if (!Utils.UserHasRating(user.ID, model.GameName))
            {
                model.ErrorText = "Запись невозможна - ваш игровой рейтинг слишком низок для записи в эту партию!";
                LogService.Warn(Utils.GetPrincipalName(), Constants.COMPONENT_SITE, string.Format("Trying to join game with insufficient rating: {0}", model.GameName));
                return View();
            }
            if (string.IsNullOrEmpty(model.GameMask))
            {
                ModelState.AddModelError("err", "Игровая маска не должна быть пустой");
            }
            if (model.GameMask.Length > 50)
            {
                ModelState.AddModelError("err", "Игровая маска не должна превышать 50 символов");
            }
            foreach (char c in model.GameMask)
            {
                if (!char.IsLetterOrDigit(c) && c != '_' && c !='-')
                {
                    ModelState.AddModelError("err", "В имени игровой маски допустимы только цифры, буквы, знак '-' и символ подчеркивания");
                }
            }
            if (Utils.MaskExists(model.GameMask, model.GameName))
            {
                ModelState.AddModelError("err", "Такая игровая маска уже есть - выберите другую");
            }
            if (string.IsNullOrEmpty(model.GameEmail))
            {
                ModelState.AddModelError("err", "Игровой email не должен быть пустым");
            }
            if (string.IsNullOrEmpty(model.GameEmailPassword))
            {
                ModelState.AddModelError("err", "Игровой пароль не должен быть пустым");
            }
            Games g = Utils.GetGame(model.GameName);
            if (model.GamePassword != g.Password)
            {
                ModelState.AddModelError("err", "Вы ввели неверный пароль - попробуйте еще раз");
            }
            if (!ModelState.IsValid)
            {
                return View();
            }
            GameUserData gud = GameUserData.CreateGameUserData(1, user.ID, model.GameName, 0, model.GameMask, model.Gender, 0, 0, false, model.GameEmailPassword, -1);
            gud.UserEmail = model.GameEmail;
            HeritageEntities ents = new HeritageEntities();
            ents.GameUserData.AddObject(gud);
            ents.SaveChanges();
            string gender = "мужской";
            if (model.Gender == 1) gender = "женский";
            if (model.Gender == 2) gender = "средний";
            if (model.Gender == 3) gender = "множественный";
            Utils.SendJoinNotification(user.Email, model.GameName, user.Username, model.GameName, model.GameMask, gender, model.GameEmailPassword);
            return new RedirectResult("/Game/JoinSuccess");
        }

        [AuthorizedValidated]
        public ActionResult JoinSuccess()
        {
            return View();
        }

        [AuthorizedValidated]
        public ActionResult InviteSuccess()
        {
            return View();
        }

        [AuthorizedValidated]
        public ActionResult AcceptInvitation()
        {
            return View();
        }

        [AuthorizedValidated]
        public ActionResult Leave(string id)
        {
            if (Utils.LeaveGame(id)) return View();
            return new RedirectResult("/Home/JoinGame");
        }

        public ActionResult LeavePair(string id)
        {
            Utils.LeavePair(id);
            return new RedirectResult("/Home/JoinGame");
        }

        [AuthorizedValidated]
        public ActionResult WhoJoined(string id)
        {
            Games g = Utils.GetGame(id);
            GameRecordModel model = new GameRecordModel();
            model.GameName = id;
            if (Utils.IsModeratorAndAbove())
            {
                model.IsModeratorMode = true;
            }
            foreach (Users u in Utils.GetGameUsers(id))
            {
                Users paired = Utils.GetPairedUser(id, u.ID);
                string descr = "";
                Guid cuid = Utils.GetCurrentUser().ID;
                if (u.ID == cuid || (paired != null && paired.ID == cuid))
                {
                    descr = " (это вы";
                    if (paired != null)
                    {
                        if (paired.ID == cuid)
                        {
                            descr += (" в паре с " + u.Username);
                        }
                        if (u.ID == cuid)
                        {
                            descr += (" в паре с " + paired.Username);
                        }
                    }
                    descr += ")";
                }
                GameRecordLine line = new GameRecordLine();
                line.GameMask = Utils.GetUserMask(u.ID, id)+"<span style=\"font-style:italic; color:red; font-weight:normal;\">"+descr+"</span>";
                line.UserRating = Utils.GetUserServerRating(u.ID) + "";
                line.UserName = u.Username;
                if (paired != null) line.UserName += ("<br>(+" + paired.Username + ")");
                line.UserID = u.ID.ToString("N");
                model.GameRecords.Add(line);
            }
            ViewData.Model = model;
            return View();
        }

        [AuthorizedValidated]
        public ActionResult Messages()
        {
            string game = Request["game"];
            ViewData["Game"] = game;
            Games g = Utils.GetGame(game);
            if (g == null) return new RedirectResult("/Home/ActiveGames");
            GameUserData gud = Utils.GetMyGameUserDataInGame(game);
            ViewData["UserData"] = gud;
            if (g == null) return new EmptyResult();
            int page = -1;
            try
            {
                page = int.Parse(Request["page"]);
            }
            catch { };
            string filter = Session["MessageFilter"] as string;
            if (string.IsNullOrEmpty(filter)) filter = "f:all";
            if (filter == "f:mafia" && !Utils.IsMafia(gud))
            {
                filter = "f:all";
            }
            HeritageEntities ents = new HeritageEntities();
            MessageModel model = new MessageModel();
            model.Page = page;
            model.GameID = game;
            model.UserData = gud;
            //if (filter == "f:guest")
            //{
            //    int count = ents.GameMessages.Where(r => r.Game == game && r.MessageTo == Constants.ADRESAT_EVERYBODY).OrderBy(t => t.MessageTime).Count();
            //    int start = page * Constants.PAGE_SIZE;
            //    int len = Constants.PAGE_SIZE;
            //    model.AllPages = (count-1) / Constants.PAGE_SIZE + 1;
            //    if (start < 0) start = count - Constants.PAGE_SIZE;
            //    if (start < 0) start = 0;
            //    model.Messages = ents.GameMessages.Where(r => r.Game == game && r.MessageTo == Constants.ADRESAT_EVERYBODY).OrderBy(t => t.MessageTime).Skip(start).Take(len).ToList();
            //}
            if (filter == "f:all")
            {
                bool isGuest = gud == null;
                Guid gudGuid = isGuest ? Guid.Empty : gud.UserID;
                bool isMafia = Utils.IsMafia(gud);
                int count = ents.GameMessages.Where(r => r.Game == game && (r.MessageTo == Constants.ADRESAT_EVERYBODY || r.MessageTo == gudGuid || r.MessageFrom == gudGuid || (isMafia && r.MessageTo == Constants.ADRESAT_MAFIA))).OrderBy(t => t.MessageTime).Count();
                int start = page * Constants.PAGE_SIZE;
                int len = Constants.PAGE_SIZE;
                model.AllPages = (count - 1) / Constants.PAGE_SIZE + 1;
                if (start < 0) start = count - Constants.PAGE_SIZE;
                if (start < 0) start = 0;
                model.Messages = ents.GameMessages.Where(r => r.Game == game && (r.MessageTo == Constants.ADRESAT_EVERYBODY || r.MessageTo == gudGuid || r.MessageFrom == gudGuid || (isMafia && r.MessageTo == Constants.ADRESAT_MAFIA))).OrderBy(t => t.MessageTime).Skip(start).Take(len).ToList();
            }
            if (filter == "f:marked")
            {
                Guid myuid = Utils.GetCurrentUser().ID;
                bool isGuest = gud == null;
                Guid gudGuid = isGuest ? Guid.Empty : gud.UserID;
                bool isMafia = Utils.IsMafia(gud);
                int count = ents.MessageFlags.Where(r => r.UserID == myuid).Join(ents.GameMessages.Where(r => r.Game == game && (r.MessageTo == Constants.ADRESAT_EVERYBODY || r.MessageTo == gudGuid || r.MessageFrom == gudGuid || (isMafia && r.MessageTo == Constants.ADRESAT_MAFIA))), u => u.MessageID, gq => gq.UID, (u, gq) => gq).OrderBy(t => t.MessageTime).Count();
                int start = page * Constants.PAGE_SIZE;
                int len = Constants.PAGE_SIZE;
                model.AllPages = (count - 1) / Constants.PAGE_SIZE + 1;
                if (start < 0) start = count - Constants.PAGE_SIZE;
                if (start < 0) start = 0;
                model.Messages = ents.MessageFlags.Where(r => r.UserID == myuid).Join(ents.GameMessages.Where(r => r.Game == game && (r.MessageTo == Constants.ADRESAT_EVERYBODY || r.MessageTo == gudGuid || r.MessageFrom == gudGuid || (isMafia && r.MessageTo == Constants.ADRESAT_MAFIA))), u => u.MessageID, gq => gq.UID, (u, gq) => gq).OrderBy(t => t.MessageTime).Skip(start).Take(len).ToList();
            }
            if (filter == "f:mafia")
            {
                bool isGuest = gud == null;
                Guid gudGuid = isGuest ? Guid.Empty : gud.UserID;
                bool isMafia = Utils.IsMafia(gud);
                int count = ents.GameMessages.Where(r => r.Game == game && r.MessageTo == Constants.ADRESAT_MAFIA && (r.MessageFrom == gudGuid || isMafia)).OrderBy(t => t.MessageTime).Count();
                int start = page * Constants.PAGE_SIZE;
                int len = Constants.PAGE_SIZE;
                model.AllPages = (count - 1) / Constants.PAGE_SIZE + 1;
                if (start < 0) start = count - Constants.PAGE_SIZE;
                if (start < 0) start = 0;
                model.Messages = ents.GameMessages.Where(r => r.Game == game && r.MessageTo == Constants.ADRESAT_MAFIA && (r.MessageFrom == gudGuid || isMafia)).OrderBy(t => t.MessageTime).Skip(start).Take(len).ToList();
            }
            if (filter == "f:news")
            {
                bool isGuest = gud == null;
                Guid gudGuid = isGuest ? Guid.Empty : gud.UserID;
                bool isMafia = Utils.IsMafia(gud);
                int count = ents.GameMessages.Where(r => r.Game == game && r.MessageTo == gudGuid && (r.MessageFrom == Constants.ADRESAT_GAZETA || r.MessageFrom == Constants.ADRESAT_GAZETA_MORNING)).OrderBy(t => t.MessageTime).Count();
                int start = page * Constants.PAGE_SIZE;
                int len = Constants.PAGE_SIZE;
                model.AllPages = (count - 1) / Constants.PAGE_SIZE + 1;
                if (start < 0) start = count - Constants.PAGE_SIZE;
                if (start < 0) start = 0;
                model.Messages = ents.GameMessages.Where(r => r.Game == game && r.MessageTo == gudGuid && (r.MessageFrom == Constants.ADRESAT_GAZETA || r.MessageFrom == Constants.ADRESAT_GAZETA_MORNING)).OrderBy(t => t.MessageTime).Skip(start).Take(len).ToList();
            }
            if (filter == "f:private")
            {
                bool isGuest = gud == null;
                Guid gudGuid = isGuest ? Guid.Empty : gud.UserID;
                bool isMafia = Utils.IsMafia(gud);
                int count = ents.GameMessages.Where(r => r.Game == game && r.IsAnonymous == false && r.MessageTo != Constants.ADRESAT_EVERYBODY && r.MessageTo != Constants.ADRESAT_MAFIA && (r.MessageFrom == gudGuid || (r.MessageTo == gudGuid && r.MessageFrom != Constants.ADRESAT_GAZETA && r.MessageFrom != Constants.ADRESAT_GAZETA_MORNING))).OrderBy(t => t.MessageTime).Count();
                int start = page * Constants.PAGE_SIZE;
                int len = Constants.PAGE_SIZE;
                model.AllPages = (count - 1) / Constants.PAGE_SIZE + 1;
                if (start < 0) start = count - Constants.PAGE_SIZE;
                if (start < 0) start = 0;
                model.Messages = ents.GameMessages.Where(r => r.Game == game && r.IsAnonymous == false && r.MessageTo != Constants.ADRESAT_EVERYBODY && r.MessageTo != Constants.ADRESAT_MAFIA && (r.MessageFrom == gudGuid || (r.MessageTo == gudGuid && r.MessageFrom != Constants.ADRESAT_GAZETA && r.MessageFrom != Constants.ADRESAT_GAZETA_MORNING))).OrderBy(t => t.MessageTime).Skip(start).Take(len).ToList();
            }
            if (filter == "f:mayor")
            {
                bool isGuest = gud == null;
                Guid gudGuid = isGuest ? Guid.Empty : gud.UserID;
                bool isMafia = Utils.IsMafia(gud);
                int count = ents.GameMessages.Where(r => r.Game == game && r.MessageFrom == Constants.ADRESAT_MAYOR).OrderBy(t => t.MessageTime).Count();
                int start = page * Constants.PAGE_SIZE;
                int len = Constants.PAGE_SIZE;
                model.AllPages = (count - 1) / Constants.PAGE_SIZE + 1;
                if (start < 0) start = count - Constants.PAGE_SIZE;
                if (start < 0) start = 0;
                model.Messages = ents.GameMessages.Where(r => r.Game == game && r.MessageFrom == Constants.ADRESAT_MAYOR).OrderBy(t => t.MessageTime).Skip(start).Take(len).ToList();
            }
            if (filter == "f:anonym")
            {
                bool isGuest = gud == null;
                Guid gudGuid = isGuest ? Guid.Empty : gud.UserID;
                bool isMafia = Utils.IsMafia(gud);
                int count = ents.GameMessages.Where(r => r.Game == game && r.IsAnonymous == true && r.MessageTo != Constants.ADRESAT_EVERYBODY && r.MessageTo != Constants.ADRESAT_MAFIA && (r.MessageFrom == gudGuid || r.MessageTo == gudGuid)).OrderBy(t => t.MessageTime).Count();
                int start = page * Constants.PAGE_SIZE;
                int len = Constants.PAGE_SIZE;
                model.AllPages = (count - 1) / Constants.PAGE_SIZE + 1;
                if (start < 0) start = count - Constants.PAGE_SIZE;
                if (start < 0) start = 0;
                model.Messages = ents.GameMessages.Where(r => r.Game == game && r.IsAnonymous == true && r.MessageTo != Constants.ADRESAT_EVERYBODY && r.MessageTo != Constants.ADRESAT_MAFIA && (r.MessageFrom == gudGuid || r.MessageTo == gudGuid)).OrderBy(t => t.MessageTime).Skip(start).Take(len).ToList();
            }

            Guid filterGuid = Guid.Empty;

            if (Guid.TryParse(filter, out filterGuid))
            {
                bool isGuest = gud == null;
                Guid gudGuid = isGuest ? Guid.Empty : gud.UserID;
                bool isMafia = Utils.IsMafia(gud);
                int count = ents.GameMessages.Where(r => r.Game == game && !r.IsAnonymous && r.MessageFrom == filterGuid && (r.MessageTo == Constants.ADRESAT_EVERYBODY || r.MessageTo == gudGuid || (isMafia && r.MessageTo == Constants.ADRESAT_MAFIA))).OrderBy(t => t.MessageTime).Count();
                int start = page * Constants.PAGE_SIZE;
                int len = Constants.PAGE_SIZE;
                model.AllPages = (count - 1) / Constants.PAGE_SIZE + 1;
                if (start < 0) start = count - Constants.PAGE_SIZE;
                if (start < 0) start = 0;
                model.Messages = ents.GameMessages.Where(r => r.Game == game && !r.IsAnonymous && r.MessageFrom == filterGuid && (r.MessageTo == Constants.ADRESAT_EVERYBODY || r.MessageTo == gudGuid || (isMafia && r.MessageTo == Constants.ADRESAT_MAFIA))).OrderBy(t => t.MessageTime).Skip(start).Take(len).ToList();
            }

            if (model.Messages == null || model.Messages.Count == 0)
            {
                model.Messages = new List<GameMessages>();
                model.AllPages = 0;
            }

            ViewData.Model = model;
            return View();
        }

        [AuthorizedValidated]
        public ActionResult View(string id)
        {
            Games g = Utils.GetGame(id);
            if (g == null) return new RedirectResult("/Home/JoinGame/");
            if (g.GameState == Constants.GAME_STATE_AVAILABLE)
            {
                return new RedirectResult("/Game/WhoJoined/" + id);
            }
            GameUserData gud = Utils.GetMyGameUserDataInGame(id);
            ViewData.Model = gud;
            ViewData["Game"] = id;
            Session["MessageFilter"] = "f:all";
            return new RedirectResult("/Game/Messages/?game=" + id);
        }
        [AuthorizedValidated]
        public ActionResult ShowMessage()
        {
            string game = Request["game"];
            Games g = Utils.GetGame(game);
            GameUserData gud = Utils.GetMyGameUserDataInGame(game);
            ViewData["Game"] = game;
            ViewData["UserData"] = gud;
            Guid uid = Guid.Empty;
            try
            {
                uid = Guid.Parse(Request["messageID"]);
            }
            catch
            {
            }
            HeritageEntities ents = new HeritageEntities();
            GameMessages gm = ents.GameMessages.Where(r => r.UID == uid && r.Game == game).FirstOrDefault();
            if (gm == null) return new RedirectResult("/Game/View/" + game);
            string filter = Session["MessageFilter"] as string;
            List<Guid> kvp = Utils.GetPrevAndNextMessages(game, gm.UID, filter);
            ViewData["PrevGuid"] = kvp[0];
            ViewData["NextGuid"] = kvp[1];
            ViewData.Model = gm;
            return View();
        }

        [AuthorizedValidated]
        public ActionResult DeclineInvitation(string id)
        {
            Guid g = Guid.Empty;
            Guid.TryParse(id, out g);
            HeritageEntities ents = new HeritageEntities();
            Invitations inv = ents.Invitations.Where(r => r.ID == g).FirstOrDefault();
            if (inv != null)
            {
                string subject = string.Format("Пользователь {0} отклонил(а) ваше предложение",
                               Utils.GetCurrentUser().Username);
                string body = string.Format("{0} отклонил(а) ваше предложение сыграть парой парой в игре {1}.", Utils.GetCurrentUser().Username, inv.Game);
                Utils.SocialMessageCreateSystem(inv.Sender, Constants.SOCIALMESSAGE_TYPE_EVENT, subject, body);
                Users whom = ents.Users.Where(r => r.ID == inv.Sender).First();
                body = string.Format("{0} отклонил(a) ваше предложение сыграть в паре в игре {1}.\n\n---------------------------\nПочтовый робот сервера netmafia.ru", Utils.GetCurrentUser().Username, inv.Game);
                Utils.SendMail(whom.Email, "Приглашение сыграть в паре отклонено", body);

                ents.Invitations.DeleteObject(inv);
                ents.SaveChanges();
            }
            return View();
        }

        [AcceptVerbs(HttpVerbs.Post)]
        [AuthorizedValidated]
        public ActionResult InviteProcess(FormCollection coll)
        {
            string invId = coll["invID"];
            string game = coll["game"];
            string email = coll["email"];
            string password = coll["password"];
            Guid g = Guid.Empty;
            Guid.TryParse(invId, out g);
            HeritageEntities ents = new HeritageEntities();
            Invitations inv = ents.Invitations.Where(r => r.ID == g).FirstOrDefault();
            GameUserData gud =
                ents.GameUserData.Where(r => r.GameName == game && r.UserID == inv.Sender && r.UserID2 == null).
                    FirstOrDefault();
            if (inv == null)
            {
                ViewData.ModelState.AddModelError("err", "Приглашение не найдено");
            }
            else if (Utils.GetMyGameUserDataInGame(inv.Game) != null)
            {
                ViewData.ModelState.AddModelError("err", "К сожалению, вы не можете принять приглашение, потому что вы уже записаны в эту партию. Отклоните его, либо выпишитесь из партии и зайдите сюда снова");
            }
            else if (gud == null)
            {
                ViewData.ModelState.AddModelError("err", "Приглашающий пользователь уже выписался из партии либо взял в пару другого игрока");
            }
            if (string.IsNullOrEmpty(email) || string.IsNullOrEmpty(password))
            {
                ViewData.ModelState.AddModelError("err", "Игровые email и пароль не должны быть пустыми");
            }
            if (!ViewData.ModelState.IsValid)
            {
                return View();
            }
            gud.UserEmail2 = email;
            gud.GamePassword2 = password;
            gud.UserID2 = Utils.GetCurrentUser().ID;
            ents.Invitations.DeleteObject(inv);
            ents.SaveChanges();
            string subject = string.Format("Пользователь {0} принял(а) ваше предложение",
                            Utils.GetCurrentUser().Username);
            string body = string.Format("{0} принял(а) ваше предложение сыграть парой парой в игре {1}.", Utils.GetCurrentUser().Username, inv.Game);
            Utils.SocialMessageCreateSystem(inv.Sender, Constants.SOCIALMESSAGE_TYPE_EVENT, subject, body);
            Users whom = ents.Users.Where(r => r.ID == inv.Sender).First();
            body = string.Format("{0} принял(a) ваше предложение сыграть в паре в игре {1}.\n\n---------------------------\nПочтовый робот сервера netmafia.ru", Utils.GetCurrentUser().Username, inv.Game);
            Utils.SendMail(whom.Email, "Приглашение сыграть в паре принято", body);
            string gender = "мужской";
            if (gud.UserGender == 1) gender = "женский";
            if (gud.UserGender == 2) gender = "средний";
            if (gud.UserGender == 3) gender = "множественный";
            Utils.SendJoinNotification(Utils.GetCurrentUser().Email, gud.GameName, Utils.GetCurrentUser().Username, gud.GameName, gud.UserMask, gender, gud.GamePassword2);
            return new RedirectResult("/Game/AcceptInvitation");
        }

        [AcceptVerbs(HttpVerbs.Post)]
        [GameMaster]
        [AuthorizedValidated]
        public ActionResult MyCodes(FormCollection coll)
        {
            try
            {
                string uid = coll["speedC"];
                int value = int.Parse(coll["quantity"]);
                if (uid == "EB")
                {
                    HeritageEntities ents = new HeritageEntities();
                    foreach (var user in ents.Users)
                    {
                        for (int i=0; i<value;i++)
                        {
                            HeritageEntities ents2 = new HeritageEntities();
                            string invcode = Utils.CreateInvCode();
                            RegistrationCodes rc = RegistrationCodes.CreateRegistrationCodes(invcode, false, 1);
                            rc.CreatedBy = user.ID;
                            ents2.AddToRegistrationCodes(rc);
                            ents2.SaveChanges();
                            ents2.Dispose();
                        }
                    }
                }
                else
                {
                    Guid whom = Guid.Parse(uid);
                    for (int i = 0; i < value; i++)
                    {
                        HeritageEntities ents2 = new HeritageEntities();
                        string invcode = Utils.CreateInvCode();
                        RegistrationCodes rc = RegistrationCodes.CreateRegistrationCodes(invcode, false, 1);
                        rc.CreatedBy = whom;
                        ents2.AddToRegistrationCodes(rc);
                        ents2.SaveChanges();
                        ents2.Dispose();
                    }
                }
            }
            catch (Exception ex)
            {
                
            }
            return new RedirectResult("/Game/MyCodes");
        }

        [AuthorizedValidated]
        public ActionResult MyCodes()
        {
            Guid id = Utils.GetCurrentUser().ID;
            HeritageEntities ents = new HeritageEntities();
            List<RegistrationCodes> codes =
                ents.RegistrationCodes.Where(r => r.CreatedBy == id).ToList();
            List<string> result = new List<string>();
            foreach(var c in codes)
            {
                string s = c.RegisterCode + ",";
                if (c.UsedBy == null) s += "свободен для регистрации";
                else
                {
                    s += string.Format("использован для регистрации игрока {0}", Utils.GetUserByID(c.UsedBy.Value.ToString("N")).Username);
                }
                result.Add(s);
            }
            ViewData.Model = result.ToArray();
            return View();
        }


        [AuthorizedValidated]
        public ActionResult InviteProcess(string id)
        {
            Guid g = Guid.Empty;
            Guid.TryParse(id, out g);
            HeritageEntities ents = new HeritageEntities();
            Invitations inv = ents.Invitations.Where(r => r.ID == g).FirstOrDefault();
            GameUserData gud = Utils.GetGameUserData(inv.Game, inv.Sender);
            if (inv == null)
            {
                ViewData.ModelState.AddModelError("err","Приглашение не найдено");
            }
            else if (Utils.GetMyGameUserDataInGame(inv.Game) != null)
            {
                ViewData.ModelState.AddModelError("err", "К сожалению, вы не можете принять приглашение, потому что вы уже записаны в эту партию. Отклоните его, либо выпишитесь из партии и зайдите сюда снова");                                    
            }
            else if (gud == null)
            {
                ViewData.ModelState.AddModelError("err", "Приглашающий пользователь уже выписался из партии");                                                    
            }
            else
            {
                ViewData.Model = gud;
            }
            ViewData["InvitationID"] = id;
            return View();
        }

        [AuthorizedValidated]
        public ActionResult WriteMessage()
        {
            string game = Request["game"];
            Games g = Utils.GetGame(game);
            GameUserData gud = Utils.GetMyGameUserDataInGame(game);
            if (gud == null)
            {
                return new RedirectResult("/Game/Messages/?game=" + game);
            }
            ViewData["Game"] = game;
            ViewData["UserData"] = gud;
            return View();
        }

        [AcceptVerbs(HttpVerbs.Post)]
        [AuthorizedValidated]
        public ActionResult Vote(FormCollection coll)
        {
            string game = coll["game"];
            Games g = Utils.GetGame(game);
            GameUserData gud = Utils.GetMyGameUserDataInGame(game);
            if (gud == null)
            {
                return new RedirectResult("/Game/Messages/?game=" + game);
            }
            string vote = coll["vote"];
            string spec = coll["spec"];
            HeritageEntities ents = new HeritageEntities();
            Guid gdv = Guid.Empty;
            Guid gdsv = Guid.Empty;
            if (!Guid.TryParse(vote, out gdv)) gdv = gud.UserID;
            if (!Guid.TryParse(spec, out gdsv)) gdsv = gud.UserID;
            GameUserData data = ents.GameUserData.Where(r => r.UserID == gud.UserID && r.GameName == game).FirstOrDefault();
            data.UserVote = gdv;
            data.UserSpecVote = gdsv;
            ents.SaveChanges();
            return new RedirectResult("/Game/Vote/?game=" + game);
        }

        [AcceptVerbs(HttpVerbs.Post)]
        [AuthorizedValidated]
        public ActionResult Invite(FormCollection coll)
        {
            string game = coll["game"];
            string user = coll["speedC"];
            Guid id = Utils.GetCurrentUser().ID;
            HeritageEntities ents = new HeritageEntities();
            Invitations inv = ents.Invitations.Where(r => r.Sender == id && r.Game == game).FirstOrDefault();
            if (inv != null) return new RedirectResult("/Home/JoinGame");
            Guid invid = Guid.NewGuid();
            Guid whomguid = Guid.Parse(user);
            ents.AddToInvitations(Invitations.CreateInvitations(invid, id, whomguid, game, DateTime.Now));
            ents.SaveChanges();
            string subject = string.Format("Пользователь {0} приглашает вас сыграть парой в игре {1}!",
                                           Utils.GetCurrentUser().Username, game);
            string body = string.Format("{0} приглашает вас сыграть парой в игре {1}.<br>Для того, чтобы согласиться или отказаться, пройдите, пожалуйста, по <a href=\"/Game/InviteProcess/{2}\">этой ссылке</a>",Utils.GetCurrentUser().Username, game, invid.ToString("N"));
            Utils.SocialMessageCreateSystem(whomguid, Constants.SOCIALMESSAGE_TYPE_EVENT, subject, body);
            Users whom = ents.Users.Where(r => r.ID == whomguid).First();
            body = string.Format("{0} приглашает вас сыграть парой в игре {1}.\nДля того, чтобы согласиться или отказаться, просмотрите свои личные сообщения на сервере.\n\n---------------------------\nПочтовый робот сервера netmafia.ru", Utils.GetCurrentUser().Username, game, invid.ToString("N"));
            Utils.SendMail(whom.Email, "Приглашение сыграть в паре", body);
            return new RedirectResult("/Game/InviteSuccess");
        }

        [AuthorizedValidated]
        public ActionResult Invite(string id)
        {
            string game = id;
            Guid idz = Utils.GetCurrentUser().ID;
            HeritageEntities ents = new HeritageEntities();
            Invitations inv = ents.Invitations.Where(r => r.Sender == idz && r.Game == game).FirstOrDefault();
            if (inv != null)
            {
                ViewData["Text"] =
                    string.Format(
                        "Вы уже отослали приглашение для игры парой в эту партию пользователю <b>{0}</b><br>Вам необходимо подождать, пока он примет либо отклонит ваше приглашение.",
                        Utils.GetUserByID(inv.Recipient.ToString("N")).Username);
            }
            ViewData["Game"] = game;
            return View();
        }


        [AuthorizedValidated]
        public ActionResult Vote()
        {
            string game = Request["game"];
            Games g = Utils.GetGame(game);
            GameUserData gud = Utils.GetMyGameUserDataInGame(game);
            if (gud == null || gud.UserState != Constants.USERSTATE_ALIVE || g.GameState == Constants.GAME_STATE_FINISHED)
            {
                return new RedirectResult("/Game/Messages/?game=" + game);
            }
            ViewData.Model = Utils.GetAllGameUsersData(game);
            ViewData["Game"] = game;
            ViewData["UserData"] = gud;
            return View();
        }

        [AuthorizedValidated]
        public ActionResult CurrentNews()
        {
            string game = Request["game"];
            Games g = Utils.GetGame(game);
            GameUserData gud = Utils.GetMyGameUserDataInGame(game);
            if (gud == null)
            {
                return new RedirectResult("/Game/Messages/?game=" + game);
            }
            ViewData.Model = Utils.GetAllGameUsersData(game);
            ViewData["Game"] = game;
            ViewData["UserData"] = gud;

            ViewData["Text"] = Utils.GetNewspaper(g, gud, false, true);
            return View();
        }

        [AcceptVerbs(HttpVerbs.Post)]
        [AuthorizedValidated]
        public ActionResult PostMessage(FormCollection coll)
        {
            string game = coll["game"];
            Guid next = Guid.Empty;
            Guid.TryParse(coll["nextguid"], out next);
            Guid adr = Guid.Empty;
            try
            {
                adr = Guid.Parse(coll["adressee"]);
            }
            catch
            {
                return new RedirectResult("/Game/View/" + game);
            }
            bool anon = coll["anonymous"] != null;
            string message = coll["msgtext"];
            GameUserData gud = Utils.GetMyGameUserDataInGame(game);
            string prefx = Utils.GetMailPrefix(gud, adr, anon);
            message = prefx + message;
            if (gud == null) return new RedirectResult("/Game/View/" + game);
            if (adr == Constants.ADRESAT_EVERYBODY || adr == Constants.ADRESAT_MAFIA) anon = false;
            HeritageEntities ents = new HeritageEntities();
            GameMessages gm = GameMessages.CreateGameMessages(1, game, DateTime.Now, message, false, gud.UserID, adr, anon, Guid.NewGuid(), Utils.GetGame(game).GameTurn, gud.UserState);
            ents.GameMessages.AddObject(gm);
            ents.SaveChanges();
            if (next != Guid.Empty)
            {
                return new RedirectResult(string.Format("/Game/ShowMessage/?messageID={0}&game={1}", next, game));                
            }
            Session["MessageFilter"] = "f:all";
            return new RedirectResult("/Game/View/" + game);
        }

        [AuthorizedValidated]
        public ActionResult Filter(string id, string id2)
        {
            Session["MessageFilter"] = "f:all";
            if (id2 == "Marked") Session["MessageFilter"] = "f:marked";
            if (id2 == "Mafia") Session["MessageFilter"] = "f:mafia";
            if (id2 == "News") Session["MessageFilter"] = "f:news";
            if (id2 == "Private") Session["MessageFilter"] = "f:private";
            if (id2 == "Anonym") Session["MessageFilter"] = "f:anonym";
            if (id2 == "Mayor") Session["MessageFilter"] = "f:mayor";
            Guid res = Guid.Empty;
            if (Guid.TryParse(id2, out res)) Session["MessageFilter"] = id2;
            return new RedirectResult("/Game/Messages/?game=" + id);
        }
        [AuthorizedValidated]
        public ActionResult MarkMessage()
        {
            string guid = Request["messageID"];
            try
            {
                Guid g = Guid.Parse(guid);
                Guid myid = Utils.GetCurrentUser().ID;
                HeritageEntities ents = new HeritageEntities();
                MessageFlags mf = ents.MessageFlags.Where(r => r.UserID == myid && r.MessageID == g).FirstOrDefault();
                if (mf != null)
                {
                    ents.MessageFlags.DeleteObject(mf);
                }
                else
                {
                    mf = MessageFlags.CreateMessageFlags(1, myid, g, Constants.FLAGGED_AS_INTERESTING);
                    ents.MessageFlags.AddObject(mf);
                }
                ents.SaveChanges();
            }
            catch { }
            return null;
        }
    }
}
